package clw.wumi.views.list;

import clw.wumi.data.entity.Item;
import clw.wumi.data.service.ItemService;
import clw.wumi.views.MainLayout;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed;

/**
 * @author chengliwei
 */
@PageTitle("WuMi | 清单")
@Route(value = "list", layout = MainLayout.class)
@AnonymousAllowed
public class ListView extends VerticalLayout {

    private final Grid<Item> grid = new Grid<>(Item.class);
    private final TextField filterText = new TextField();

    private ItemForm form;
    private final ItemService service;

    public ListView(ItemService service) {
        this.service = service;
        addClassName("list-view");
        setSizeFull();
        configureGrid();
        configureForm();

        add(getToolbar(), getContent());
        updateList();
        closeEditor();
    }

    private void configureGrid() {
        grid.addClassName("item-grid");
        grid.setSizeFull();
        grid.setColumns();
        grid.addColumn(Item::getId).setHeader("ID");
        grid.addColumn(Item::getName).setHeader("名称");
        grid.addColumn(item -> item.getPlace().getName()).setHeader("位置");
        grid.addColumn(item -> item.getParentItem() == null ? "" : item.getParentItem().getName()).setHeader("上级");
        grid.addColumn(Item::getNum).setHeader("数量");
        grid.addColumn(Item::getDesc).setHeader("描述");
        grid.getColumns().forEach(col -> col.setAutoWidth(true));

        grid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES);

        grid.asSingleSelect().addValueChangeListener(listener -> editItem(listener.getValue()));
    }

    private void configureForm() {
        form = new ItemForm(service.findAllPlaces(), service.findAllItems(null));
        form.setWidth("25em");

        form.addSaveListener(this::saveItem);
        form.addDeleteListener(this::deleteItem);
        form.addCloseListener(e -> closeEditor());
    }

    private void updateList() {
        grid.setItems(service.findAllItems(filterText.getValue()));
    }

    private Component getContent() {
        HorizontalLayout content = new HorizontalLayout(grid, form);
        content.setFlexGrow(2, grid);
        content.setFlexGrow(1, form);
        content.addClassName("content");
        content.setSizeFull();
        return content;
    }

    private HorizontalLayout getToolbar() {
        filterText.setPlaceholder("根据名称搜索...");
        filterText.setPrefixComponent(new Icon(VaadinIcon.SEARCH));
        filterText.setClearButtonVisible(true);
        filterText.setValueChangeMode(ValueChangeMode.LAZY);
        filterText.addValueChangeListener(e -> updateList());

        Button addButton = new Button("新增物品");
        addButton.addClickListener(click -> addItem());

        var toolbar = new HorizontalLayout(filterText, addButton);
        toolbar.addClassName("toolbar");
        return toolbar;
    }

    private void addItem() {
        grid.asSingleSelect().clear();
        editItem(new Item());
    }

    private void editItem(Item item) {
        if (item == null) {
            closeEditor();
        } else {
            form.setItem(item);
            form.setVisible(true);
            addClassName("editing");
        }
    }

    private void closeEditor() {
        form.setItem(null);
        form.setVisible(false);
        removeClassName("editing");
    }

    private void saveItem(ItemForm.SaveEvent event) {
        service.saveItem(event.getItem());
        updateList();
        closeEditor();
    }

    private void deleteItem(ItemForm.DeleteEvent event) {
        service.deleteItem(event.getItem());
        updateList();
        closeEditor();
    }
}
